package com.pet.system.security.shiro;

import com.pet.system.domain.entity.SysUser;
import com.pet.system.domain.model.LoginUser;
import com.pet.system.security.jwt.JwtToken;
import com.pet.system.security.jwt.JwtTools;
import com.pet.system.service.IPermissionService;
import com.pet.system.service.ISysUserService;
import lombok.AllArgsConstructor;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.springframework.stereotype.Component;

import java.util.Set;

/**
 * MyRealm
 *
 * @author Centaurea
 */
@Component
@AllArgsConstructor
public class MyRealm extends AuthorizingRealm {
  private final ISysUserService userService;
  private final IPermissionService permissionService;
  private final JwtTools jwtTools;

  @Override
  public boolean supports(AuthenticationToken token) {
    return token instanceof JwtToken;
  }

  @Override
  protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
    // TODO 根据用户名称，查询对应的权限，特殊处理：SUPER_ADMIN 目前可拥有 *:*:*
    // 存 LoginUser, 同时缓存
    LoginUser loginUser = (LoginUser) principalCollection.getPrimaryPrincipal();
    Set<String> permissions = permissionService.getPermissions(loginUser.getId());
    SimpleAuthorizationInfo simpleAuthorizationInfo = new SimpleAuthorizationInfo();
    simpleAuthorizationInfo.setStringPermissions(permissions);

    return simpleAuthorizationInfo;
  }

  @Override
  protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken)
      throws AuthenticationException {
    // 获取用户
    String token = (String) authenticationToken.getPrincipal();
    LoginUser loginUser = jwtTools.getLoginUser(token);
    try {
      SysUser user = userService.getByUserName(loginUser.getUsername());
      loginUser.setPassword(user.getPassword());
    } catch (Exception e) {
      throw new AuthenticationException("认证时发生异常:" + e.getCause().getMessage());
    }
    if (!jwtTools.verify(token, loginUser)) {
      throw new AuthenticationException("认证非法");
    }
    return new SimpleAuthenticationInfo(loginUser, token, loginUser.getUsername());
  }
}
